message: json::Json,
}
process_builder.exec_with_streaming(
- &mut |line| assert!(line.is_empty()),
+ &mut |line| if !line.is_empty() {
+ Err(internal(&format!("compiler stdout is not empty: `{}`", line)))
+ } else {
+ Ok(())
+ },
&mut |line| {
- let rustc_message = json::Json::from_str(line).unwrap_or_else(|_| {
- panic!("Compiler produced invalid json: `{}`", line)
- });
+ let rustc_message = try!(json::Json::from_str(line).map_err(|_| {
+ internal(&format!("compiler produced invalid json: `{}`", line))
+ }));
let message = Message {
reason: "rustc-message",
};
let encoded = json::encode(&message).unwrap();
println!("{}", encoded);
-
+ Ok(())
},
).map(|_| ())
} else {
pub desc: String,
pub exit: Option<ExitStatus>,
pub output: Option<Output>,
- cause: Option<io::Error>,
+ cause: Option<Box<Error + Send>>,
}
impl Error for ProcessError {
fn description(&self) -> &str { &self.desc }
fn cause(&self) -> Option<&Error> {
- self.cause.as_ref().map(|s| s as &Error)
+ self.cause.as_ref().map(|e| &**e as &Error)
}
}
// Construction helpers
pub fn process_error(msg: &str,
- cause: Option<io::Error>,
+ cause: Option<Box<Error + Send>>,
status: Option<&ExitStatus>,
- output: Option<&Output>) -> ProcessError {
+ output: Option<&Output>) -> ProcessError
+{
let exit = match status {
Some(s) => status_to_string(s),
None => "never executed".to_string(),
use std::path::Path;
use std::process::{Command, Stdio, Output};
-use util::{ProcessError, process_error, read2};
+use util::{CargoResult, ProcessError, process_error, read2};
use util::shell_escape::escape;
#[derive(Clone, PartialEq, Debug)]
let exit = try!(command.status().map_err(|e| {
process_error(&format!("could not execute process `{}`",
self.debug_string()),
- Some(e), None, None)
+ Some(Box::new(e)), None, None)
}));
if exit.success() {
let output = try!(command.output().map_err(|e| {
process_error(&format!("could not execute process `{}`",
- self.debug_string()),
- Some(e), None, None)
+ self.debug_string()),
+ Some(Box::new(e)), None, None)
}));
if output.status.success() {
}
pub fn exec_with_streaming(&self,
- on_stdout_line: &mut FnMut(&str),
- on_stderr_line: &mut FnMut(&str))
+ on_stdout_line: &mut FnMut(&str) -> CargoResult<()>,
+ on_stderr_line: &mut FnMut(&str) -> CargoResult<()>)
-> Result<Output, ProcessError> {
let mut stdout = Vec::new();
let mut stderr = Vec::new();
.stderr(Stdio::piped())
.stdin(Stdio::null());
+ let mut callback_error = None;
let status = try!((|| {
let mut child = try!(cmd.spawn());
let out = child.stdout.take().unwrap();
let start = dst.len();
dst.extend(data);
for line in String::from_utf8_lossy(&dst[start..]).lines() {
- if is_out {
+ if callback_error.is_some() { break }
+ let callback_result = if is_out {
on_stdout_line(line)
} else {
on_stderr_line(line)
+ };
+ if let Err(e) = callback_result {
+ callback_error = Some(e);
}
}
}));
})().map_err(|e| {
process_error(&format!("could not execute process `{}`",
self.debug_string()),
- Some(e), None, None)
+ Some(Box::new(e)), None, None)
}));
let output = Output {
stdout: stdout,
Err(process_error(&format!("process didn't exit successfully: `{}`",
self.debug_string()),
None, Some(&output.status), Some(&output)))
+ } else if let Some(e) = callback_error {
+ Err(process_error(&format!("failed to parse process output: `{}`",
+ self.debug_string()),
+ Some(Box::new(e)), Some(&output.status), Some(&output)))
} else {
Ok(output)
}